//
//  PropWarper.swift
//  medepend
//
//  Created by zhu xietong on 2023/11/29.
//

import Foundation

public class PublishProp:NSObject{
    func update(value:BaseValue) {
    }
}

public class PropUpdate:NSObject{
    func update(value:BaseValue) {
    }
}





@propertyWrapper
public class Prop<Value:BaseValue>:PropUpdate{
    public var value: Value
    public var wrappedValue: Value{
        set{
            value = newValue
            projectedValue.onNext(newValue)
        }
        get{
            return value
        }
    }
    
    public init(wrappedValue defaultValue: Value) {
        self.value = defaultValue
    }
    
    override func update(value:BaseValue) {
        // 示例用法
        do {
            let v = try convertValue(value, toType: Value.self)
            wrappedValue = v
        } catch {
            print("Error: \(error)")
        }
    }
    
    public var projectedValue: PublishSub<Value> = PublishSub<Value>()
}

enum ConversionError: Error {
    case invalidConversion
}

extension Dictionary{
    func get<U:BaseValue>(_ key:String,_ type: U.Type)->U?{
        guard let k = key as? Key,let v = self[k] else {
            return nil
        }
        do {
            let value = try convertValue(v, toType: type)
            return value
        } catch {
            return nil
        }
        
        
    }
}

func convertValue<T, U:BaseValue>(_ value: T, toType type: U.Type) throws -> U {
    let valueType = Mirror(reflecting: value).subjectType
    let targetType = type
    
    

    
    guard valueType != targetType else {
        // 如果源类型和目标类型相同，直接返回原始值
        return value as! U
    }
    
 
    
    var stringValue = "\(value)"
    
    switch targetType {
    case is String.Type:
        return stringValue as! U
    case is CGFloat.Type:
        guard let floatValue = Float(stringValue) else {
            throw ConversionError.invalidConversion
        }
        return CGFloat(floatValue) as! U
    case is Float.Type:
        guard let floatValue = Float(stringValue) else {
            throw ConversionError.invalidConversion
        }
        return floatValue as! U
    case is Double.Type:
        guard let doubleValue = Double(stringValue) else {
            throw ConversionError.invalidConversion
        }
        return doubleValue as! U
    case is Int.Type:
        guard let intValue = Int(stringValue) else {
            guard let floatValue = Float(stringValue) else {
                throw ConversionError.invalidConversion
            }
            let intValue = Int(floatValue)
            return intValue as! U
        }
        return intValue as! U
    case is Bool.Type:
        if(stringValue == "1"){
            stringValue = "true"
        }
        if(stringValue == "0"){
            stringValue = "false"
        }
        guard let boolValue = Bool(stringValue) else {
            throw ConversionError.invalidConversion
        }
        return boolValue as! U
    case is Dictionary<AnyHashable,Any>.Type:
        if let dict = value as? [AnyHashable:Any]{
            return dict as! U
        }else{
            throw ConversionError.invalidConversion
        }
    
    default:
        throw ConversionError.invalidConversion
    }
}

public class Assgin{
    public static func assgin(of object:Any,dict:[AnyHashable:Any]) {
        let props = getProps(of: object)
        let propKeys = props.keys
        for key in propKeys {
            let p = key.replace(regex: "^_", with: "")
            let wrap = props[key]
            if let v = dict[p] as? BaseValue{
                wrap?.update(value: v)
            }
        }
    }
    
    
    public static func getProps(of object: Any)->[String:PropUpdate]{
        var properties: [String: PropUpdate] = [:]
        // 递归获取 Mirror
        func processMirror(_ mirror: Mirror) {
            for child in mirror.children {
                // 获取属性名（label）
                guard let label = child.label else {
                    continue
                }
                // 获取属性值
                if let value = child.value as? PropUpdate{
                    // 存储属性名和属性值到字典
                    properties[label] = value
                }
            }
            // 递归处理父类的 Mirror
            if let superclassMirror = mirror.superclassMirror {
                processMirror(superclassMirror)
            }
        }
        // 获取对象的 Mirror
        let mirror = Mirror(reflecting: object)
        
        // 处理 Mirror
        processMirror(mirror)
        // 打印结果
        return properties
        //    print(properties)
    }
}

